
/** @file multi_index.h
 *
 * Interface to multi_index
 *
 */

/*
 *  Copyright (C) 2003 Stefan Weinzierl
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __SECTOR_DECOMPOSITION_MULTI_INDEX_H__
#define __SECTOR_DECOMPOSITION_MULTI_INDEX_H__

#include <ostream>
#include <cstddef>
#include <vector>

namespace sector_decomposition {

  /**
   *
   * basic_multi_index is a base class.
   *
   */
  class basic_multi_index {

	// ctors
    public :  
      basic_multi_index(void);
      explicit basic_multi_index(size_t N, size_t k);
      explicit basic_multi_index(size_t N, const std::vector<size_t> & vv);

	// functions 
    public :
      size_t size(void) const;
      bool overflow(void) const;

        // subscripting
    public :  
      size_t operator[](size_t i) const;
      size_t & operator[](size_t i);

      size_t operator()(size_t i) const;
      size_t & operator()(size_t i);

        // virtual functions
    public :  
        // initialization
      virtual basic_multi_index & init(void);
        // postfix increment
      virtual basic_multi_index & operator++ (int);
 
        // I/O operators
      friend std::ostream & operator<< (std::ostream & os, const basic_multi_index & v);

	// member variables :
    protected : 
      /// upper limit for all components
      size_t N;
      /// a vector holding the multi-index
      std::vector<size_t> v;
      /// a flag indicating overflow
      bool flag_overflow;

  };

  /**
   *
   * The class multi_index_ordered defines a multi_index
   * \f$(n_1,n_2,...,n_k)\f$, such that
   * \f[
   *     0 \le n_j < N
   * \f]
   * and
   * \f[
   *     n_j < n_{j+1}.
   * \f]
   * It is assumed that \f$k>0\f$ and \f$ N \ge k \f$.
   * 
   */
  class multi_index_ordered : public basic_multi_index {

	// ctors
    public :  
      multi_index_ordered(void);
      explicit multi_index_ordered(size_t N, size_t k);
      explicit multi_index_ordered(size_t N, const std::vector<size_t> & vv);

        // overriding virtual functions from base class
    public :  
        // initialization
      basic_multi_index & init(void);
        // postfix increment
      basic_multi_index & operator++ (int);
 
        // I/O operators
      friend std::ostream & operator<< (std::ostream & os, const multi_index_ordered & v);

  };

  /**
   *
   * The class multi_index_counter defines a multi_index
   * \f$(n_1,n_2,...,n_k)\f$, such that
   * \f[
   *     0 \le n_j < N
   * \f]
   * 
   */
  class multi_index_counter : public basic_multi_index {

	// ctors
    public :  
      multi_index_counter(void);
      explicit multi_index_counter(size_t N, size_t k);
      explicit multi_index_counter(size_t N, const std::vector<size_t> & vv);

        // overriding virtual functions from base class
    public :  
        // initialization
      basic_multi_index & init(void);
        // postfix increment
      basic_multi_index & operator++ (int);
 
        // I/O operators
      friend std::ostream & operator<< (std::ostream & os, const multi_index_counter & v);

  };

  /**
   *
   * The class multi_index_counter_indv defines a multi_index
   * \f$(n_1,n_2,...,n_k)\f$, such that
   * \f[
   *     0 \le n_j < N_j
   * \f]
   * 
   */
  class multi_index_counter_indv : public basic_multi_index {

	// ctors
    public :  
      multi_index_counter_indv(void);
      explicit multi_index_counter_indv(const std::vector<size_t> & Nv, size_t k);
      explicit multi_index_counter_indv(const std::vector<size_t> & Nv, const std::vector<size_t> & vv);

        // overriding virtual functions from base class
    public :  
        // initialization
      basic_multi_index & init(void);
        // postfix increment
      basic_multi_index & operator++ (int);
 
        // I/O operators
      friend std::ostream & operator<< (std::ostream & os, const multi_index_counter_indv & v);

	// member variables :
    protected : 
      /// upper limit for the individual components
      std::vector<size_t> Nv;
  };

} // namespace sector_decomposition

#endif // ndef __SECTOR_DECOMPOSITION_MULTI_INDEX_H__

